package btb.ui;

import de.matthiasmann.twl.Alignment;
import de.matthiasmann.twl.Button;
import de.matthiasmann.twl.CallbackWithReason;
import de.matthiasmann.twl.Label;
import de.matthiasmann.twl.ListBox;
import de.matthiasmann.twl.TextArea;
import de.matthiasmann.twl.ListBox.CallbackReason;
import de.matthiasmann.twl.ResizableFrame.ResizableAxis;
import de.matthiasmann.twl.textarea.SimpleTextAreaModel;
import btb.engine.CDisplayTask;
import btb.util.CLogger;

public class CGuiLobby extends AGuiObject
{
	public static final int DISPLAY_OPT_GUEST 			= 0;
	public static final int DISPLAY_OPT_HOST 			= 1;
	
	private boolean showingHostLobby;
	
	private Label lblPlayers;
	private Label lblInfo;
	
	private ListBox<String> lstPlayers;
	
	private TextArea txtInfo;
	private SimpleTextAreaModel txtInfoModel;
	
	public CChatFrame frmLobbyChat;
	
	private Button btnStart;
	private Button btnKick;
	private Button btnBan;
	private Button btnLeave;
	
	private CallbackWithReason<ListBox.CallbackReason> lstPlayersCallback = null;
	private Runnable btnKickCallback = null;
	private Runnable btnBanCallback = null;
	private Runnable btnLeaveCallback = null;
	
	private String username;
	
	public CGuiLobby(CDisplayTask _parent, boolean _showHostLobby)
	{
		super(_parent, _showHostLobby ? DISPLAY_OPT_HOST : DISPLAY_OPT_GUEST);
		showingHostLobby = _showHostLobby;
	}

	@Override
	public void initializeGUI(int _guiDisplayOption)
	{
		initializeDisplay(DEFAULT_WINDOW_WIDTH, DEFAULT_WINDOW_HEIGHT, "Beat the Bard Prototype", BTB_THEME_02_FILEPATH, _guiDisplayOption);
	}

	@Override
	protected void initializeWidgets(int _guiDisplayOption)
	{
		username = "default_user";
		
		lblPlayers		= new Label();
		lblInfo			= new Label();
		
		lstPlayers		= new ListBox<String>();
		
		txtInfo			= new TextArea();
		txtInfoModel	= new SimpleTextAreaModel();
				
		frmLobbyChat	= new CChatFrame(this.username);
		
		if(_guiDisplayOption == DISPLAY_OPT_HOST)
		{
			btnStart		= new Button();
			btnKick			= new Button();
			btnBan			= new Button();
		}
		btnLeave		= new Button();
	}

	@Override
	protected void addWidgets(int _guiDisplayOption)
	{
		addNewLabel(this.lblPlayers, "gamelabel", "Players Joined");
		addNewLabel(this.lblInfo, "gamelabel", "Map Info");

		addNewListBox(this.lstPlayers, "gamelistbox");
		
		addNewTextArea(this.txtInfo, "gametextarea", "", this.txtInfoModel);
		
		addNewWidget(this.frmLobbyChat, "chatframe");
		
		try
		{
			if(_guiDisplayOption == DISPLAY_OPT_HOST)
			{
				addNewButton(this.btnStart, "submitbutton", "Start Game");
				addNewButton(this.btnKick, "submitbutton", "Refresh Lists");
				addNewButton(this.btnBan, "submitbutton", "Logout");
			}
		}
		catch(Exception e){CLogger.cond_error("ui/display", "addWidgets() for lobby page; Display option conditional. Generic exception thrown.");}
		addNewButton(this.btnLeave, "submitbutton", "Exit");
	}

	@Override
	protected void setLayout(int _guiDisplayOption)
	{
		// [Labels for players joined list box and map info text box]
		resizeWidgetRelativeToWindow(this.lblPlayers, 8f / 32, 1f / 32, true);
		copyWidgetSize(this.lblInfo, this.lblPlayers);
		placeWidgetInEqualRow(this.lblPlayers, 1, 2, 2.5f / 32, true);
		placeWidgetInEqualRow(this.lblInfo, 2, 2, this.lblPlayers.getY(), false);
		this.lblPlayers.setAlignment( Alignment.CENTER );
		this.lblInfo.setAlignment( Alignment.CENTER );

		// [Players joined list box and map info text box]
		resizeWidgetRelativeToWindow(this.lstPlayers, 12f / 32, 8f / 32, false);
		copyWidgetSize(this.lstPlayers, this.txtInfo);
		placeWidgetInEqualRow(this.lstPlayers, 1, 2, 3.5f / 32, true);
		placeWidgetInEqualRow(this.txtInfo, 2, 2, this.lstPlayers.getY(), false);
		
		// [Chat Frame]
		resizeWidgetRelativeToWindow(this.frmLobbyChat, 26f / 32, 14.5f / 32, false);
		placeWidgetAgainstWindow(this.frmLobbyChat, 3f / 32, 13f / 32, false, false);
		this.frmLobbyChat.setResizableAxis(ResizableAxis.NONE);
		
		// [Buttons]
		try
		{
			if(_guiDisplayOption == DISPLAY_OPT_HOST)
			{
				resizeWidgetRelativeToWindow(this.btnStart, 8f / 32, 1.5f / 32, true);
				copyWidgetSize(this.btnStart, this.btnKick);
				copyWidgetSize(this.btnStart, this.btnBan);
				copyWidgetSize(this.btnStart, this.btnLeave);
				placeWidgetInEqualRow(this.btnStart, 1, 4, 29f / 32, true);
				placeWidgetInEqualRow(this.btnKick, 2, 4, this.btnStart.getY(), false);
				placeWidgetInEqualRow(this.btnBan, 3, 4, this.btnStart.getY(), false);
				placeWidgetInEqualRow(this.btnLeave, 4, 4, this.btnStart.getY(), false);
			}
			else
			{
				resizeWidgetRelativeToWindow(this.btnLeave, 8f / 32, 1.5f / 32, true);
			}
		}
		catch(Exception e){CLogger.cond_error("ui/display", "setLayout() for lobby page; Display option conditional. Generic exception thrown.");}
	}

	@Override
	protected void resetPage(int _guiDisplayOption)
	{
		// TODO Auto-generated method stub
	}

	@Override
	protected void removeCallBacks(int _guiDisplayOption)
	{
		if(lstPlayersCallback != null)
			lstPlayers.removeCallback(lstPlayersCallback);
		if(btnKickCallback != null)
			btnKick.removeCallback(btnKickCallback);
		if(btnBanCallback != null)
			btnBan.removeCallback(btnBanCallback);
		if(btnLeaveCallback != null)
			btnLeave.removeCallback(btnBanCallback);				
	}
	
	@Override
	protected void addCallBacks(int _guiDisplayOption)
	{
		if(_guiDisplayOption == DISPLAY_OPT_HOST && true) //[Refactoring]: Add a condition here, to check some other, more authoritative variable.
		{
			lstPlayersCallback = new CallbackWithReason<ListBox.CallbackReason>()
			{
				@Override
				public void callback(CallbackReason cbreason)
				{
					if(cbreason == CallbackReason.SET_SELECTED || cbreason == CallbackReason.MOUSE_CLICK)
					{
						// [Development]: Set the selected user for kick/ban operations. 
						// [Development]: If any functionality other than setting the selected player is needed...
					}
				}	
			};

			btnKickCallback = new Runnable()
			{	
				public void run()
				{
					attemptPlayerKick();			
				}
			};
			
			btnBanCallback = new Runnable()
			{	
				public void run()
				{
					attemptPlayerBan();	
				}
			};
		}
		
		btnLeaveCallback = new Runnable(){public void run(){attemptLeaveSession();}};
		
		if(_guiDisplayOption == DISPLAY_OPT_HOST && true)
		{
			this.lstPlayers.addCallback(lstPlayersCallback);
			this.btnKick.addCallback(btnKickCallback);
			this.btnBan.addCallback(btnBanCallback);
		}
		this.btnLeave.addCallback(btnLeaveCallback);
	}

	public void attemptPlayerKick()
	{
		// [Development]: functionality here should send a "KICK PLAYER" message containing the user profile of the player in question.
		// The metaserver should, upon authorization, then remove the player from the session, send that player's client a "YOU GOT KICKED" message,
		// which should cause the client to return to the hub.
	}
	
	public void attemptPlayerBan()
	{
		// [Development]: functionality here should send a "BAN PLAYER" message containing the user profile of the player in question.
		// The metaserver should, upon authorization, then remove the player from the session, send that player's client a "YOU GOT BANNED" message,
		// which should cause the client to return to the hub. That player should also be added to that session's list of banned players.
		// Any player on that list should be refused entry to that session. 
	}
	
	public void attemptLeaveSession()
	{
		// [Development]: functionality here should send "LEAVING SESSION" message to metaserver. When the metaserver responds with a
		// "YOU HAVE LEFT" message, after removing the sending user from the session object, the client should return to the hub.
	}
}
